package exercise.day05;


import utils.ArrayUtils;

/***
 * @author hunter.d
 * @qq 657270652
 * @wx haitao-duan
 * @date 2021/3/6
 *
 * 超级经典的练习题！！！！
 * 反复做10遍都不为过！！！
 * 题中所涉及的知识点：
 *   - 变量定义语法，
 *   - 变量赋值语法，
 *   - 数组定义、创建语法，
 *   - 数组取值、更新值、遍历等语法，
 *   - if判断语法，
 *   - 循环控制语法；
 *   - 方法封装，
 *   - 方法调用
 *
 * 并且有一定的逻辑思维训练效果
 * 做完这些题，java的基础语法瞬间全部搞定
 *
 **/
public class _03_方法加强Exercise {

    /**
     * 定义一个方法：数组扩充元素
     *    参数： 一个整数数组arr 和 一个整数 i
     *    功能： 给arr数组扩展一个元素i
     *    返回： 扩展后的新数组
     *
     *  比如，传入数组  [3,5,10] 和一个整数 20
     *  返回一个数组  [3,5,10,20]
     *
     * 思路：
     *    旧数组不可能添加元素，而是生成一个新数组，装入旧数组所有元素及新增的那个元素
     *
     */

    static int[] arrayAppendInt(int[] arr,int ele){

        // 创建一个数组，用来装结果数据
        int[] result = new int[arr.length+1];

        // 遍历旧数组，取出每一个元素赋值给新数组上的每一个元素
        for(int i=0;i<arr.length;i++){
            result[i] = arr[i];
        }

        // 将新数组的最后一个元素，赋值为ele的值
        result[arr.length] = ele;

        // 返回结果数组
        return result;
    }


    /**
     * 定义一个方法：数组拼接
     *    参数： 一个整数数组arr1 和 另一个个整数 arr2
     *    功能： 将两个数组拼接成一个数组
     *    返回： 拼接后的新数组
     *
     */
    static int[] arrayAppendArray(int[] arr1,int[] arr2){
        int[] result = new int[arr1.length+arr2.length];

        for(int i=0;i<arr1.length;i++){
            result[i] = arr1[i];
        }

        for(int j=0;j<arr2.length;j++){
            result[arr1.length+j] = arr2[j];
        }

        return result;
    }


    /**
     * 定义一个方法，数组去重
     *    参数： 一个整数数组arr1
     *    功能： 对数组中的元素去重
     *    返回： 去重后的数组
     *   [2,3,2,5,6,5,5] --> [2,3,5,6]
     *  思路：
     *     1. 创建一个临时数组，长度等于输入的数组
     *     2. 找到输入数组的最大值，给临时数组的所有元素初始化为 ： max+1
     *     3. 遍历输入数组，拿到一个元素，就判断是否存在于tmp数组
     *          如果存在，啥也不做
     *          如果不存在，将这个元素放入tmp数组，并且计数器+1
     *     4. 从tmp数组中取出“计数器”个元素，放入一个返回数组，返回即可
     *
     */
    // 前置方法1，给定一个数组，返回最大值  ArrayUtils.findMax(数组)
    // 前置方法2，判断一个整数，是否存在于一个数组中  ArrayUtils.ifExists(数组,元素)

    static int[] arrayDistinct(int[] arr){
        // 创建临时数组
        int[] tmp = new int[arr.length];
        // 初始化临时数组
        for(int i=0;i<tmp.length;i++){
            tmp[i] = ArrayUtils.findMax(arr) + 1;
        }

        // 定义一个去重元素个数的计数器
        int num = 0;
        for (int i=0;i<arr.length;i++){
            if(!ArrayUtils.ifExists(tmp,arr[i])){
                // 如果不存在，将这个元素放入tmp数组，并且计数器+1
                tmp[num] = arr[i];
                num++;
            }
        }

        // 新建一个返回数组
        int[] result = new int[num];
        for(int i=0;i<num;i++){
            result[i] = tmp[i];
        }

        return result;
    }




    /**
     * 定义一个方法，数组求差集
     *    参数： 一个整数数组arr1 和 另一个个整数 arr2
     *    功能： 从arr1中剔除掉存在于arr2中的元素
     *    返回： 剔除后剩余的元素的数组
     *    arr1: [2,3,3,2,5,6]  arr2:[2,5,7,8]
     *    返回：[3,3,6]
     *
     *
     *    思路：遍历arr1，拿到一个元素就去判断，是否存在于arr2中，如果不存在，则存入一个临时数组
     */
    static int[] arrayDiff(int[] arr1,int[] arr2){

        int[] tmp = new int[arr1.length];

        int count = 0;
        for (int i=0;i<arr1.length;i++){
            // 如果数组1中的第i元素，不存在于数组2中，则将它存入tmp数组
            if(!ArrayUtils.ifExists(arr2,arr1[i])){
                tmp[count] = arr1[i];
                count++;
            }
        }

        // 从tmp中取出前count个元素，生成一个新数组
        int[] diff = new int[count];
        for(int i=0;i<count;i++){
            diff[i] = tmp[i];
        }

        // 对diff去重
        int[] result = arrayDistinct(diff);


        return result;
    }




    /**
     * 定义一个方法，数组求交集
     *    参数： 一个整数数组arr1 和 另一个个整数 arr2
     *    功能： 求arr1和arr2的交集
     *    返回： 交集的结果数组
     *
     *     arr1: [2,3,3,2,5,6]  arr2:[2,5,7,8]
     *    返回：[2,5]
     *
     */
    static int[] arrayIntersect(int[] arr1,int[] arr2){
        // 创建一个临时数组，用于存放交集元素
        int[] tmp = new int[arr1.length];
        int count = 0;

        // 遍历数组1，拿到第i元素去数组2中判断是否存在
        for(int i=0;i<arr1.length;i++){
            // 如果第i元素存在于arr2中，则将第i元素存入tmp数组
            if(ArrayUtils.ifExists(arr2,arr1[i])){
                tmp[count] = arr1[i];
                count++;
            }
        }

        // 从tmp中取出前count个交集元素，放入交集数组
        int[] intersect = new int[count];
        for(int i=0;i<count;i++){
            intersect[i] = tmp[i];
        }

        // 对交集元素去重
        int[] result = arrayDistinct(intersect);

        return  result;
    }




    /**
     * 定义一个方法，数组求并集
     *    参数： 一个整数数组arr1 和 另一个个整数 arr2
     *    功能： 求arr1和arr2的并集
     *    返回： 去重后的并集结果
     *
     *
     *    输入：[2,3,5]  [3,6,8]
     *    返回：[2,3,5,6,8]
     */
    static int[] arrayUnion(int[] arr1,int[] arr2){

        // 创建一个临时数组，用于存放两个输入数组的元素
        // 直接调用咱们上面已经定义好的数组拼接方法
        int[] arr = arrayAppendArray(arr1, arr2);

        // 对拼接后的结果数组去重，即可
        int[] result = arrayDistinct(arr);

        return  result;
    }

    /**
     * 定义一个方法，对一个数组进行逆序
     *    参数： 一个整数数组arr1
     *    功能： 把数组的首尾元素对调
     *    返回： 调整后的结果数组
     *             i   j
     *    比如： [1,2,3,4,5] len:5
     *    返回： [5,4,3,2,1]
     *
     *    思路：
     *       i的遍历范围： i>=0,  i<len/2
     *       对调元素（i, (len-1)-i) ==> 0,4   1,3
     */
    static void arrayReverse(int[] arr){
        for(int i=0;i<arr.length/2;i++){
            int j = arr.length-1-i;
            int tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        }
    }


    /**
     * 定义一个方法，对数组中的数据按照由小到大排序
     *    参数： 一个整数数组arr1
     *    功能： 调整arr1中的数据顺序，让其变得有序
     *    返回： 调整后的结果数组
     *
     *    比如： [3,2,5,7,1]
     *    返回： [1,2,3,5,7]
     */

    static void arraySortBubble(int[] arr){

        // 控制 对调操作 的轮次

        // 记死：  外层i循环到len-1
        //        内层j循环到len-1-i
        for(int i=0;i<arr.length-1;i++){
            for (int j=0;j<arr.length-1-i;j++){
                // 判断，对调j和j+1的元素
                if(arr[j]>arr[j+1]){
                    int tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                }
            }
        }
    }


    public static void main(String[] args) {
        int[] test = {3,4,55,10};
        int[] result = arrayAppendInt(test, 19);

        // ArrayUtils类，是在utils包中
        // 而printArray(int[])方法，是在ArrayUtils类中
        ArrayUtils.printArray(result);

        System.out.println("--------天堂-------");

        int[] a1 = {2,3,4,6,7,9,3};
        int[] a2 = {6,7,10};
        int[] ints = arrayAppendArray(a1, a2);
        ArrayUtils.printArray(ints);

        System.out.println("--------隐形的翅膀-------");


        // 去重方法的调用测试
        int[] a3 = {3,4,3,6,5,6,5,6,6,7};
        int[] res3 = arrayDistinct(a3);
        ArrayUtils.printArray(res3);

        System.out.println("--------隐形的翅膀-------");

        // 两个数组求差集，调用测试
        int[] res4 = arrayDiff(a1, a2);
        ArrayUtils.printArray(res4);

        System.out.println("--------隐形的翅膀-------");
        int[] res5 = arrayIntersect(a1, a2);
        ArrayUtils.printArray(res5);


        System.out.println("--------涛哥的铁粉：超哥-------");
        arrayReverse(a1);
        ArrayUtils.printArray(a1);


        System.out.println("--------排序算法是咱们课程中唯一需要你背诵的-------");
        arraySortBubble(a1);
        ArrayUtils.printArray(a1);

    }

}
